package admission.ecnu.service;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.json.JSONArray;
import org.json.JSONObject;

import admission.ecnu.dao.ResultDAO;
import admission.ecnu.dao.classInfoDao;
import admission.ecnu.dao.teacherInfoDao;
import admission.ecnu.interfaces.IRnsService;
import admission.ecnu.mainservlet.RnsContext;
import admission.ecnu.object.DataManager;
import admission.ecnu.object.OClassInfo;
import admission.ecnu.object.OResult;
import admission.ecnu.object.OTeacherInfo;

import com.ecnu.sei.app.Scheduler;
import com.ecnu.sei.app.course.AbstractCourse;
import com.ecnu.sei.app.course.CourseInfo;
import com.ecnu.sei.app.course.ExamInfo;
import com.ecnu.sei.app.course.PublicCompulsory;
import com.ecnu.sei.app.course.SpecialtyCompulsory;
import com.ecnu.sei.app.course.SpecialtyElective;
import com.ecnu.sei.app.resources.Classroom;
import com.ecnu.sei.app.resources.Time;
import com.ecnu.sei.app.teacher.AbstractTeacher;
import com.ecnu.sei.app.teacher.Administrator;
import com.ecnu.sei.app.teacher.AssociateProfessor;
import com.ecnu.sei.app.teacher.ForeignTeacher;
import com.ecnu.sei.app.teacher.Lecturer;
import com.ecnu.sei.app.teacher.Official;
import com.ecnu.sei.app.teacher.Professor;
import com.ecnu.sei.app.util.Utils;

public class getExamArrangement implements IRnsService {

	private List<OResult>result = new ArrayList<OResult>();
  private static HashMap<String, AbstractTeacher> tIdToITeacherMap = new HashMap<String, AbstractTeacher>();

  @Override
  public void executeService(RnsContext context) throws Exception {
    // TODO Auto-generated method stub
    JSONObject obj = context.getJsonRequestObject();
    System.out.print(obj.toString());
    if (!DataManager.USER_ID.equals(obj.get("key"))) {
      JSONObject jsonReturn = new JSONObject();
      jsonReturn.put("returnCode", DataManager.RETURN_WRONGKEY);
      context.setJsonResponseObject(jsonReturn);
      return;
    }
    
//    List resultList = new ResultDAO().resultSelect();
//    if(resultList.size()>0)
//    	new ResultDAO().resultDelete();

    loadTeacherInfo();
    loadClassInfo();
    setExamTime(DataManager.compStartTime,DataManager.compEndTime,DataManager.elecStartTime,DataManager.elecEndTime);
    Scheduler.getScheduler().generateSchedule();
    
    result = getExamSchedule();

    JSONObject jsonReturn = new JSONObject();
    JSONArray jsonReturnValue = new JSONArray();
    
    //List resultList = new ResultDAO().resultSelect();
    
    for( int i =0; i<result.size(); i++){
    	JSONObject jsonItem = new JSONObject();
    	OResult itemOResult =  result.get(i);
    	System.out.print("result:"+itemOResult+"\n");
    	//jsonItem.put("course_id", itemOResult.getCourse_id());
    	Map others = new classInfoDao().classGetOthersById(itemOResult.getCourse_id());
    	
    	jsonItem.put("course_name", others.get("course_name"));
    	//jsonItem.put("course_name", new classInfoDao().classGetNameById(itemOResult.getCourse_id()));
    	
    	String strDateAndTimeString = itemOResult.getTest_time().trim();
    	String[] itemStrings = strDateAndTimeString.substring(6,strDateAndTimeString.length()-2).split(",");
    	
    	jsonItem.put("test_time", itemStrings[1].split("=")[1]);
    	jsonItem.put("test_date", itemStrings[0].split("=")[1]);
    	
    	jsonItem.put("grade", others.get("grade"));
    	
    	//jsonItem.put("classroom", itemOResult.getClassroom()==null?" ":itemOResult.getClassroom());
    	jsonItem.put("classroom", others.get("classroom"));
    	jsonItem.put("teacher", others.get("teacher"));
    	jsonItem.put("chief_teacher", itemOResult.getChief_teacher());
    	jsonItem.put("vice_teacher01", itemOResult.getVice_teacher01());
    	jsonItem.put("vice_teacher02", itemOResult.getVice_teacher02());
    	jsonItem.put("patrol_teacher", itemOResult.getPatrol_teacher()==null?" ":itemOResult.getPatrol_teacher());
    	jsonItem.put("backup_teacher", itemOResult.getBackup_teacher());
    	
    	jsonReturnValue.put(jsonItem);
    	
    	jsonItem = null;
    	itemOResult = null;
    }

    jsonReturn.put("returnCode", DataManager.RETURN_SUCCESSFUL);
    jsonReturn.put("returnValue", jsonReturnValue);
    
    System.out.print(jsonReturn);
    Scheduler.getScheduler().clear();
	result = null;
    
    context.setJsonResponseObject(jsonReturn);

  }

  private static void loadClassInfo() {
    ArrayList<OClassInfo> classDBObjList = (ArrayList<OClassInfo>) new classInfoDao()
        .classSelect();

    
    for (OClassInfo classObj : classDBObjList) {
      CourseInfo courseInfo = new CourseInfo(
    		  classObj.getClassId(),
    		  classObj.getGrade(), 
    		  classObj.getClassName(),
    		  tIdToITeacherMap.get(classObj.getTeacher()), 
    		  Integer.valueOf(classObj.getClassDay()),// dayOfWeek
    		  Utils.getDayHourFromStartTime(Integer.valueOf(classObj.getClassTime().split("-")[0].split(":")[0])), // dayHour
              Integer.valueOf(classObj.getStudentNum()), 
              new Classroom(classObj.getClassroom(), Integer.MAX_VALUE));
      System.out.print(courseInfo.toString()+"\n");
      Scheduler scheduler = Scheduler.getScheduler();
      if (classObj.getType().equals("公共必修")) {
        scheduler.addCourse(new PublicCompulsory(courseInfo));
      } else if (classObj.getType().equals("专业必修")) {
        scheduler.addCourse(new SpecialtyCompulsory(courseInfo));
      } else if (classObj.getType().equals("专业选修")) {
        scheduler.addCourse(new SpecialtyElective(courseInfo));
      }
      
    }
  }

  private static void loadTeacherInfo() {
    ArrayList<OTeacherInfo> teacherDBObjList = (ArrayList<OTeacherInfo>) new teacherInfoDao()
        .teacherSelect();
    for (OTeacherInfo teacherObj : teacherDBObjList) {
    	System.out.print(teacherObj.toString()+"\n");
      AbstractTeacher teacher = null;
      String teacherId = teacherObj.getTeacherId();
      String teacherName = teacherObj.getName();
      if (teacherObj.getTitle().trim().equals("副教授")) {
        teacher = new AssociateProfessor(teacherId, teacherName);
      } else if (teacherObj.getTitle().trim().equals("外籍教师")) {
        teacher = new ForeignTeacher(teacherId, teacherName);
      } else if (teacherObj.getTitle().trim().equals("领导")) {
        teacher = new Administrator(teacherId, teacherName);
      } else if (teacherObj.getTitle().trim().equals("讲师")) {
        teacher = new Lecturer(teacherId, teacherName);
      } else if (teacherObj.getTitle().trim().equals("行政")) {
        teacher = new Official(teacherId, teacherName);
      } else if (teacherObj.getTitle().trim().equals("教授")) {
        teacher = new Professor(teacherId, teacherName);
      }
      tIdToITeacherMap.put(teacherId, teacher);
      Scheduler.getScheduler().addTeacher(teacher);

    }
  }

  public void setExamTime() {
	    Scheduler scheduler = Scheduler.getScheduler();
	    Time compStart = new Time(System.currentTimeMillis());
	    scheduler.setCompulsoryStartTime(compStart);
	    Time compEnd = new Time(compStart);
	    compEnd.addDays(4);
	    scheduler.setCompulsoryEndTime(compEnd);
	    
	    Time elecStart = new Time(compEnd);
	    elecStart.addDays(3);
	    scheduler.setElectiveStartTime(elecStart);
	    Time elecEnd = new Time(elecStart);
	    elecEnd.addDays(4);
	    scheduler.setElectiveEndTime(elecEnd);
  }
  
  public List<OResult> getExamSchedule() {
    List<OResult> results = new ArrayList<OResult>();
    Collection<Set<AbstractCourse>> all = Scheduler.getScheduler()
        .getExamSchedule().values();
    for (Iterator<Set<AbstractCourse>> iterator = all.iterator(); iterator
        .hasNext();) {
      Set<AbstractCourse> courseSet = iterator.next();
      for (AbstractCourse course : courseSet) {
        results.add(getResult(course));
      }
    }
    return results;
  }

  private OResult getResult(AbstractCourse course) {
    CourseInfo info = course.getCourseInfo();
    ExamInfo examInfo = info.getExamInfo();
    AbstractTeacher chief = examInfo.getChief();
    AbstractTeacher[] vices = examInfo.getVices();
    OResult result = new OResult();
    result.setCourse_id(info.getCourseId());
    result.setCourse_name(info.getCourseName());
    result.setTest_time(examInfo.getTime().toString());
    result.setChief_teacher(chief.getName());

    result.setVice_teacher01(vices[0].getName());
    if (2 == vices.length) {
      result.setVice_teacher02(vices[1].getName());
    }

    if (!(course instanceof SpecialtyElective)) {
    	result.setPatrol_teacher(examInfo.getPatrol().getName());
    }
    result.setBackup_teacher(examInfo.getBackup().getName());

    return result;
  }
  
  public void setExamTime(long compStartTime, long compEndTime, long elecStartTime, long elecEndTime) {
	    Scheduler scheduler = Scheduler.getScheduler();
	    
	    Time compStart = new Time(compStartTime);
	    scheduler.setCompulsoryStartTime(compStart);
	    
	    Time compEnd = new Time(compEndTime);
	    scheduler.setCompulsoryEndTime(compEnd);
	    
	    Time elecStart = new Time(elecStartTime);
	    scheduler.setElectiveStartTime(elecStart);
	    Time elecEnd = new Time(elecEndTime);
	    scheduler.setElectiveEndTime(elecEnd);
}
}